﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;

namespace FFMPEGWrapper
{
    public static class FFMPEGHelpers
    {
        public static Process process;

        public static MediaFile getMediaInformation(string ffmpegPath, string filePath)
        {
            MediaFile file = new MediaFile(filePath);

            StreamReader reader;

            string fulltext = "";

            RunFFMPEG(ffmpegPath, string.Format(@"-i ""{0}""", filePath), out reader);
            string line = "";
            while ((line = reader.ReadLine()) != null)
            {
                fulltext += "\n" + line;
                if (!file.VideoBitrate.HasValue)
                {
                    Match match = Regex.Match(line, @"bitrate: [0-9]+ kb/s");
                    if (match.Captures.Count > 0)
                    {
                        file.VideoBitrate = Int32.Parse(Regex.Match(match.Value, @"[0-9]+").Value);
                        //continue;
                    }
                }

                if (!file.AudioBitrate.HasValue)
                {
                    Match match = Regex.Match(line, @"Audio: .* kb/s");
                    if (match.Captures.Count > 0)
                    {
                        file.AudioBitrate = Int32.Parse(Regex.Match(line, @"([0-9\.]*) kb/s").Value.Replace(" kb/s", ""));
                        //continue;
                    }
                }

                if (!file.Duration.HasValue)
                {
                    Match match = Regex.Match(line, @"Duration: [0-9][0-9]:[0-9][0-9]:[0-9][0-9]\.*[0-9]*");
                    if (match.Captures.Count > 0)
                    {
                        var v = Regex.Match(match.Value, @"[0-9][0-9]:[0-9][0-9]:[0-9][0-9]\.*[0-9]*").Value;
                        file.Duration = TimeSpan.Parse(Regex.Match(match.Value, @"[0-9][0-9]:[0-9][0-9]:[0-9][0-9]\.*[0-9]*").Value);
                        //continue;
                    }
                }

                if (!file.VerticalResolution.HasValue || !file.HorizontalResolution.HasValue)
                {
                    Match match = Regex.Match(line, @"Video: .*");
                    if (match.Captures.Count > 0)
                    {
                        Match match2 = Regex.Match(match.Value, @"Video: .* ([0-9]+)x([0-9]+)");
                        file.HorizontalResolution = Int32.Parse(match2.Groups[1].Value);
                        file.VerticalResolution = Int32.Parse(match2.Groups[2].Value);
                        //file.Duration = TimeSpan.Parse(Regex.Match(match.Value, @"Video: .* ([0-9]+)x([0-9]+)").Value);
                        //continue;
                    }
                }

                if (string.IsNullOrEmpty(file.VideoCodec))
                {
                    Match match = Regex.Match(line, @"Video: [A-Za-z0-9]+, ");
                    if (match.Captures.Count > 0)
                    {
                        file.VideoCodec = (Regex.Matches(match.Value, @"[A-Za-z0-9]+")[1].Value).ToString();
                        //continue;
                    }
                }

                if (string.IsNullOrEmpty(file.AudioCodec))
                {
                    Match match = Regex.Match(line, @"Audio: [A-Za-z0-9]+, ");
                    if (match.Captures.Count > 0)
                    {
                        file.AudioCodec = (Regex.Matches(match.Value, @"[A-Za-z0-9]+")[1].Value).ToString();
                        //continue;
                    }
                }
            }

            return file;
        }

        public static void LoadFrames(string ffmpegPath, string filePath, string outputPath, TimeSpan startTime, int frameCount)
        {
            StreamReader reader;
            RunFFMPEG(ffmpegPath,
                string.Format(@"-vframes {3} -ss {2} -i ""{0}"" -f image2 ""{1}\output_frame_%d.bmp""",
                filePath,
                outputPath,
                startTime.ToString(),
                frameCount.ToString()),
                out reader);
            while (!reader.EndOfStream) { reader.Read(); }

        }

        public static void LoadFrame(string ffmpegPath, string filePath, string outputPath, TimeSpan timeStamp, bool frameOn)
        {
            StreamReader reader;
            RunFFMPEG(ffmpegPath,
                string.Format(@"-vframes {3} -ss {2} -i ""{0}"" -f image2 ""{1}\output_frame_{4}.bmp""",
                filePath,
                outputPath,
                timeStamp.ToString(),
                1,
                frameOn ? "A" : "B"),
                out reader);
            while (!reader.EndOfStream) { reader.Read(); }
        }

        public static void PerformCropping(string ffmpegPath, string filePath, string outputPath, int cropTop, int cropBottom, int cropLeft, int cropRight,
            string videoCodec, string audioCodec, int videoBitrate, int audioBitrate, out StreamReader reader)
        {
            RunFFMPEG(ffmpegPath,
                string.Format(@"-i ""{6}"" -vcodec {4} -b {5}Kbps -acodec copy -cropbottom {0} -croptop {1} -cropleft {2} -cropright {3} ""{7}""",
                cropTop.ToString(),
                cropBottom.ToString(),
                cropLeft.ToString(),
                cropRight.ToString(),
                videoCodec,
                videoBitrate,
                filePath,
                filePath.Insert(filePath.LastIndexOf('.'), "_CROPPED")),
                out reader);
        }

        private static void RunFFMPEG(string ffmpegPath, string Arguments, out StreamReader reader)
        {
            process = new Process();
            process.StartInfo.FileName = ffmpegPath;
            process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            process.StartInfo.CreateNoWindow = true;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.RedirectStandardError = true;
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.Arguments = Arguments;
            process.EnableRaisingEvents = true;

            process.Start();
            reader = process.StandardError;
        }
    }
}
